<script setup lang="ts" name="GoodsSku">
import { GoodsInfo, Spec, SpecValue } from '@/types/goods'
import bwPowerSet from '@/utils/power-set'
// goods 商品信息          - 选择/禁用功能
// skuId 商品的规格属性id   - 回显功能 (对应的规格按钮选中) 
// 子组件(goods-sku)选中了全部规格之后, 利用子传父, 将sku传递给父组件(goods/index.vue)
const props = defineProps<{
  goods: GoodsInfo,
  skuId?: string
}>()

const emit = defineEmits<{
  (e: 'changeSku', skuId: string): void
}>()


// 获取路径字典
const getPathMap = () => {
  const pathMap: {
    [key: string]: string[]
  } = {}
  // 1. 过滤掉库存 inventory为0的sku
  const skus = props.goods.skus.filter(item => item.inventory > 0)
  // console.log('有效的sku组合', skus);
  // 2. 遍历有效的sku组合, 得到sku的幂集
  skus.forEach(item => {
    // 3. 获取所有属性的映射集合 -> valueName (蓝色, 中国, 30cm)
    const arr = item.specs.map(sub => sub.valueName)
    // console.log('小属性的集合', arr);
    // 4. 通过powerSet工具函数 -> 获取到幂集
    const powerSet = bwPowerSet(arr)
    // console.log('获取对应的幂集', powerSet);
    // 5. 将幂集的数据合并到路径字典中
    powerSet.forEach(sub => {
      // 判断pathMap中是否有key 
      const key = sub.join('+')
      if (key in pathMap) {
        // 存在, 数组中追加
        pathMap[key].push(item.id)  // '中国' :[101, 102, 103,...]
      } else {
        // 不存在, 赋值  "10cm"
        pathMap[key] = [item.id]
      }
    })
  })
  return pathMap
}
// 可走的路径字典
const pathMap = getPathMap()
console.log(pathMap);
// 获取选中的规格
// ['', '', '']
// ['黑色', '', '']
// ['', '中国', '']
// ['', '', '10cm']
const getSelectedSpec = () => {
  const arr: string[] = []
  props.goods.specs.forEach(spec => {
    const temp = spec.values.find(item => item.selected)
    // console.log('获取选中的规格属性', temp);
    arr.push(temp ? temp.name : '')
  })
  return arr
}
// 选中状态切换
const changeSelected = (item: Spec, sub: SpecValue) => {
  // console.log('item - 每一行', item);
  // console.log('sub -  某一个', sub);
  // 禁用的规格属性  - 不应该选中
  if (sub.disabled) return
  // 1. 如果已经选中了, 取消选中
  if (sub.selected) {
    sub.selected = false
  } else {
    // 2. 如果没有选中
    // 2.1 遍历所有的同级, 利用排他思想
    item.values.forEach(item => item.selected = false)
    // 2.2 再让自身高亮
    sub.selected = true
  }
  // 在点击规格属性的时候, 需要更新禁用状态
  updateDisabledStatus()

  // 判断规格是否全部选中
  const selected = getSelectedSpec().filter(item => item)  
  // console.log(selected.length);
  if(selected.length === props.goods.specs.length) {
    // 全部选中之后
    // 去pathMap中找对应的skuId
    const key = selected.join('+')  // '黑色+30cm+中国'
    // console.log(pathMap[key]);
    const [skuId] = pathMap[key]
    // 子传父 
    emit('changeSku', skuId)  
  } else {
    // 没有全部选中
    emit('changeSku', '')
  }

}

// 更新按钮的禁用状态
// 遍历所有的规格属性, 判断规格是否存在于可选的路径集合中(pathMap), 如果说不存在, 开启禁用 
const updateDisabledStatus = () => {
  // 获取选中的规格属性 ['', '', '']
  const selectedArr = getSelectedSpec()
  // console.log('获取选中的规格属性, 原数据', selectedArr);
  props.goods.specs.forEach((item, index) => {
    item.values.forEach(sub => {
      // 尝试让当前点击的这个按钮和selectedArr进行组合 ['蓝色', '日本', '30cm']
      // 需要先拷贝一份原数组
      const tempArr = [...selectedArr]
      tempArr[index] = sub.name   // ['黑色', '中国', '30cm']
      // console.log('组合后的数组', tempArr);
      // 将得到的组合 转成字符串 '黑色+中国'
      const key = tempArr.filter(item => item).join('+')
      // console.log('组合key', key);
      // 判断当前的规格的名字是否存在于pathMap中
      if (key in pathMap) {
        // 规格名字, 存在, 不禁用
        sub.disabled = false
      } else {
        // 规格名字, 不存在, 禁用
        // console.log('不存在的规格名字', sub.name);
        sub.disabled = true
      }
    })
  })
}

// 初始化默认选中状态
const initSelectedSpec = () => {
  const sku = props.goods.skus.find(item => item.id === props.skuId)
  console.log(sku);
  if (sku) {
      // 默认选中....
      props.goods.specs.forEach((item, index) => {
        // 获取sku选中的规格属性 - 蓝色 中国 10cm
        const value = sku.specs[index].valueName
        // console.log(value);
        // 让对应的规格所选中
        const spec = item.values.find(sub => sub.name === value)
        // console.log('spec', spec);
        spec!.selected = true
      })
  }
}
initSelectedSpec()     // 初始化默认选中状态 - 先设置默认选中 
updateDisabledStatus() // 更新按钮的禁用状态 - 再去更新禁用状态
</script>
<template>
  <div class="goods-sku">
    <!-- 
      选中 - 高亮 img/span   添加 selected
      禁用 -                 添加 disabled
      默认 -                 不需要添加任何类名    
 
      img/span 后台返回的数据中, 如果该规格中包含img信息, 展示img
                               如果不包含, 展示文本span
     -->
    <dl v-for="item in goods.specs" :key="item.id">
      <dt>{{ item.name }}</dt>
      <dd>
        <template v-for="sub in item.values" :key="sub.name">
          <!-- item -> 每一行 (颜色, 尺寸,产地...)-->
          <!-- sub  -> 每一行中的某一个 (黑色, 蓝色, 20cm, 30cm)  -->
          <img @click="changeSelected(item, sub)" v-if="sub.picture" :src="sub.picture"
            :class="{ selected: sub.selected, disabled: sub.disabled }" alt="" />
          <span v-else @click="changeSelected(item, sub)" :class="{ selected: sub.selected, disabled: sub.disabled }">{{
              sub.name
          }}</span>
        </template>
      </dd>
    </dl>
  </div>
</template>

<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;

  &.selected {
    border-color: @xtxColor;
  }

  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}

.goods-sku {
  padding-left: 10px;
  padding-top: 20px;

  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;

    dt {
      width: 50px;
      color: #999;
    }

    dd {
      flex: 1;
      color: #666;

      >img {
        width: 50px;
        height: 50px;
        margin-top: 5px;
        .sku-state-mixin ();
      }

      >span {
        display: inline-block;
        height: 30px;
        line-height: 30px;
        padding: 0 20px;
        margin-top: 5px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>

